﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;
using SilentVoice.Models;
using System.Data.Entity.Validation;
using System.Data.Entity.Infrastructure;
using System.Data;
using System.Data.Entity.ModelConfiguration.Conventions;

namespace SilentVoice.Data
{
    public class NotesContext : DbContext
    {
        public DbSet<Account> Accounts { get; set; }
        public DbSet<Event> Events { get; set; }
        public DbSet<Group> Groups { get; set; }
        public DbSet<ScratchPad> ScratchPads { get; set; }
        public DbSet<User> Users { get; set; }
        public DbSet<Role> Roles { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            //TODO: consider cascade deletes
            //TODO: validation for uniqueness
            modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
            modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();

            modelBuilder.Entity<User>()
                .HasMany(u => u.Events)
                .WithRequired()
                .HasForeignKey(fk => fk.OwnerId);

            modelBuilder.Entity<User>()
                .HasMany(u => u.ScratchPads)
                .WithRequired()
                .HasForeignKey(fk => fk.OwnerId);

            modelBuilder.Entity<User>()
                .HasMany(g => g.Groups)
                .WithMany(u => u.Users);

            modelBuilder.Entity<Event>()
                .HasMany(e => e.AllowedGroups)
                .WithMany(g => g.Events)
                .Map(m => m.ToTable("EventAllowedGroups"));

            modelBuilder.Entity<User>()
                .Property(f => f.CreatedAt)
                .HasColumnType("datetime2");

            modelBuilder.Entity<User>()
                .Property(f => f.ModifiedAt)
                .HasColumnType("datetime2");

            modelBuilder.Entity<Account>()
                .Property(f => f.CreatedAt)
                .HasColumnType("datetime2");

            modelBuilder.Entity<Account>()
                .Property(f => f.ModifiedAt)
                .HasColumnType("datetime2");

            modelBuilder.Entity<Group>()
                .Property(f => f.CreatedAt)
                .HasColumnType("datetime2");

            modelBuilder.Entity<Group>()
                .Property(f => f.ModifiedAt)
                .HasColumnType("datetime2");

            modelBuilder.Entity<ScratchPad>()
                .Property(f => f.CreatedAt)
                .HasColumnType("datetime2");

            modelBuilder.Entity<ScratchPad>()
                .Property(f => f.ModifiedAt)
                .HasColumnType("datetime2");

            modelBuilder.Entity<Event>()
                .Property(f => f.CreatedAt)
                .HasColumnType("datetime2");

            modelBuilder.Entity<Event>()
                .Property(f => f.ModifiedAt)
                .HasColumnType("datetime2");
        }

        protected override DbEntityValidationResult ValidateEntity(
            DbEntityEntry entityEntry, IDictionary<object, object> items)
        {
            var myItems = new Dictionary<object, object>();

            myItems.Add("Context", this);

            return base.ValidateEntity(entityEntry, myItems);
        }

        public override int SaveChanges()
        {
            foreach(var entry in ChangeTracker.Entries<Auditable>())
            {
                var entity = entry.Entity;
                if (entry.State == EntityState.Added)
                {
                    entity.CreatedAt = DateTime.Now;
                    //entity.CreatedBy = ...;
                }
                else if (entry.State == EntityState.Modified)
                {
                    entity.ModifiedAt = DateTime.Now;
                    //entity.ModifiedBy = ...;
                }
            }

            return base.SaveChanges();
        }
    }
}